/*
* INSANE - Interactive Structural Analysis Environment
*
* Copyright (C) 2003-2005
* Universidade Federal de Minas Gerais
* Escola de Engenharia
* Departamento de Engenharia de Estruturas
* 
* Author's email :    insane@dees.ufmg.br
* Author's website :  http://www.dees.ufmg.br/insane
* 
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
* 
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
package br.ufmg.dees.insane.model.femModel.element;

import java.util.ArrayList;
import java.util.ListIterator;

import br.ufmg.dees.insane.materialMedia.degeneration.Degeneration;
import br.ufmg.dees.insane.materialMedia.degeneration.PrescribedDegeneration;
import br.ufmg.dees.insane.materialMedia.degeneration.Representation;
import br.ufmg.dees.insane.materialMedia.material.Material;
import br.ufmg.dees.insane.util.IMatrix;
import br.ufmg.dees.insane.util.INaturalCoords;
import br.ufmg.dees.insane.util.IPoint3d;
import br.ufmg.dees.insane.util.IVector;
import br.ufmg.dees.insane.util.extrapolation.LagrangeanExtrapolation2D;
import br.ufmg.dees.insane.util.numericalIntegration.GaussPoint;
import br.ufmg.dees.insane.util.numericalIntegration.IntegrationPoint;

/**
*A class representing a thin plate element.<p>
*
*@author Samir
*@version 1.0
*@since 13/09/2006
*/

public class ThinPlateElement extends Element {
	
	private static final long serialVersionUID = 1L;

	/**Constructs a ThinPlateElement.*/	
	public ThinPlateElement(){
	}

	/** Updates all variables of this element based on the nodal variables state.
	*/
	public void update(){
        ListIterator mps = degenerations.listIterator();
        while(mps.hasNext()) {
            Degeneration degeneration = (Degeneration) mps.next();
            degeneration.update();
        }
    }
	
    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.model.femModel.element.Element#getElmCoefficient()
     */
    public double getElmCoefficient(){
    	return 1;
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.model.femModel.element.Element#addDegeneration(br.ufmg.dees.insane.materialMedia.degeneration.Degeneration)
     */
    public void addDegeneration(Degeneration dg){
			try {
				this.degenerations.add((PrescribedDegeneration)(((PrescribedDegeneration)dg).clone()));
			}
			catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
    }
    
    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.model.femModel.element.Element#initDegeneration()
     */
	public void initDegenerations(){
		int k = 1;
		IntegrationPoint ip = new GaussPoint();
		int cont = (int)Math.sqrt(this.degenerations.size());
		for(int i = 0; i < cont; i++) 
		{
			for(int j = 0; j < cont; j++)
			{
			    Representation representation = new Representation();
				INaturalCoords nc = new INaturalCoords();
				nc.setCsi1(ip.getCoord((cont-1),i));
				nc.setCsi2(ip.getCoord((cont-1),j));
				representation.setNaturalcoords(nc);
				representation.setWeight(ip.getWeight((cont-1),i)*
				        	 ip.getWeight((cont-1),j));
				representation.setAnalysisModel(this.getAnalysisModel());
				representation.setCm(this.getConstitutiveModel());
                ((Degeneration)this.getDegenerations().get(k-1)).setRepresentation(representation);
                ((Degeneration)this.getDegenerations().get(k-1)).setLabel("IP-"+k);
                k++;
			}
		}

//		IntegrationPoint ip = new GaussPoint();
//	    Representation representation = new Representation();
//		INaturalCoords nc = new INaturalCoords();
//		nc.setCsi1(ip.getCoord(0,0));
//		nc.setCsi2(ip.getCoord(0,0));
//		representation.setNaturalcoords(nc);
//		representation.setWeight(ip.getWeight(0,0)*ip.getWeight(0,0));
//		representation.setAnalysisModel(this.getAnalysisModel());
//		representation.setCm(this.getConstitutiveModel());
//        ((Degeneration)this.getDegenerations().get(0)).setRepresentation(representation);
//        ((Degeneration)this.getDegenerations().get(0)).setLabel("IP-1");
	}
	
	/**
	 * Returns this FrameElement's PrescribedDegeneration's Height
	 * @return This FrameElement's PrescribedDegeneration's Height
	 */
	public double getThickness(){
		return (((PrescribedDegeneration)this.getDegenerations().get(0)).getThickness());
	}
	
//	public double getThickness(){
//		return (((Degeneration)this.getDegenerations().get(0)).getGeometricProperties().getThickness());
//	}

	public double getYoungsModulus(){
		Material mat = (((PrescribedDegeneration)this.getDegenerations().get(0)).getMaterial());
		return mat.getPs().getElement(0,0);
	}

	public double getPoissonsRatio(){
		Material mat = (((PrescribedDegeneration)this.getDegenerations().get(0)).getMaterial());
		return mat.getPs().getElement(0,1);	}
	
	/** Return the IVector containing the cartesian coordinates of a point.
	*@param point The natural coordinates of the point.
	*@return The IVector containing the cartesian coordinates of a point.
	*/
	public IVector getCartesianPointCoords(double[] point) {
	    IMatrix MatrixN = this.analysisModel.getGeometricOperator(this.Shape.getShapeFunction(point,this.getCartesianNodalCoordsMatrix()));
	    IVector pointCoords = new IVector(MatrixN.getNumRow());
		pointCoords.mul(MatrixN, this.getCartesianNodalCoordsVector());
	    return pointCoords;
	}

	@Override
	public IVector extrapolatesToNodes(ArrayList natCoords, ArrayList value) {
		LagrangeanExtrapolation2D extra = new LagrangeanExtrapolation2D(natCoords,value);
		IMatrix nodeNatCoords = this.Shape.getNaturalNodalCoords();
		IVector values = new IVector(nodeNatCoords.getNumCol());
		for (int i = 0; i < nodeNatCoords.getNumCol(); i++) {
			IPoint3d p = new IPoint3d(nodeNatCoords.getElement(0,i),nodeNatCoords.getElement(1,i));
			values.setElement(i,extra.extrapolateTo(p));
		}
		return values;
	}
	
//	/* (non-Javadoc)
//	 * @see br.ufmg.dees.insane.model.femModel.element.Element#getPointInternalVariables(br.ufmg.dees.insane.materialMedia.degeneration.Degeneration)
//	 */
//	public IVector getPointInternalVariables(Degeneration dg) {
//		double[] a = dg.getRepresentation().getNaturalcoords().toDouble();
//		IVector displ = new IVector(this.getStateVariables());
//		IMatrix T = analysisModel.getTransformationMatrix(Shape.getDerivedShapeFunction(a,this.getCartesianNodalCoordsMatrix()),this.getCartesianNodalCoordsMatrix()); 
//		IMatrix MatrixB = analysisModel.getInternalVariableOperator(Shape.getDerivedShapeFunction(a,this.getCartesianNodalCoordsMatrix()), Shape.getSecondDerivedShapeFunction(a,this.getCartesianNodalCoordsMatrix()), Shape.getShapeFunction(a,this.getCartesianNodalCoordsMatrix()), this.getCartesianNodalCoordsMatrix());
//		MatrixB = analysisModel.modifyInternalVariableOperator(MatrixB,null);
//		return(MatrixB.mul(T.mul(displ)));
//	}	

}

